﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using FPP.Models;
using FPP.Custom;
using FPP.Utilities;

namespace FPP.Controllers
{
    public class FamousPeopleController : BaseController
    {
        const int OutputCache = 30;

        new readonly fppEntities _context;

        public FamousPeopleController()
        {
            _context = new fppEntities(DataAccess.ffpCString);
        }

        [OutputCache(Duration = OutputCache)]
        public ActionResult Index()
        {
            Services.CheckServicesAsync();

            var nowPlusYear = DateTime.Now.AddYears(-1);

            using (_context)
            {
                var q =
                    _context.FamousPersons.Where(fp => fp.DateOfDeath == null || fp.DateOfDeath > nowPlusYear).OrderBy(
                        fp => fp.DisplayName);

                var famousP = q.ToArray();
                return View(famousP);
            }
        }

        //
        // GET: /FamousPeople/Details/
        public ActionResult Details(int id)
        {
            FamousPerson famousP;

            using (_context)
            {
                famousP = _context.FamousPersons.Single(g => g.Id == id);
                if (UpdateFromWikiData(ref famousP))
                {
                    _context.ForceSave(famousP);
                }
            }
            return View(famousP);
        }

        //
        // GET: /FamousPeople/Create/
        [CustomAuthorize]
        public ActionResult Create()
        {
            return View();
        }

        //
        // POST: /FamousPeople/Create/
        [HttpPost]
        [CustomAuthorize]
        public ActionResult Create(FamousPerson newFp)
        {
            if (!ModelState.IsValid) return View(newFp);
            User player = GetUserFromLoginToken(provider.SessionId);

            using (var newContext = new fppEntities(DataAccess.ffpCString))
            {
                newFp.AddedBy = player.Id;
                newFp.DisplayName = "";
                newFp.DateOfBirth = DateTime.Now;

                var repo = new FppRepository(newContext);
                if (!repo.AddFamousPerson(newFp))
                {
                    return RedirectToAction("Index");
                }
                //Call the wiki update to force the system to look for the missing link 
                var wUtil = new WikiUtil();
                wUtil.UpdateWiki(newFp.WikiLink);

                //Checks the database for changes to the wiki information, if none found it creates a record
                UpdateFromWikiData(ref newFp);

                newContext.SaveChanges();
            }

            //Get the information from the wiki table
            if (!UpdateFromWikiData(ref newFp) || newFp.DisplayName == null)
            {
                return View("CreateManual", newFp);
            }

            var urlToRemove = Url.Action("Index");
            Response.RemoveOutputCacheItem(urlToRemove);
            return RedirectToAction("Index");

        }

        //
        // GET: /FamousPeople/CreateHelp/
        [CustomAuthorize]
        public ActionResult CreateManual()
        {
            var newFp = new FamousPerson();
            return View(newFp);
        }

        //
        // GET: /FamousPeople/Edit/2
        [CustomAuthorize]
        public ActionResult Edit(int id)
        {
            FamousPerson famousP;

            using (_context)
            {
                famousP = _context.FamousPersons.Single(g => g.Id == id);
                //if (UpdateFromWikiData(ref famousP)) context.SaveChanges();
            }
            return View(famousP);
        }

        [HttpPost]
        [CustomAuthorize]
        public ActionResult Edit(int id, FormCollection formValues)
        {
            FamousPerson famousP;

            using (_context)
            {
                famousP = _context.FamousPersons.Single(g => g.Id == id);

                if (TryUpdateModel(famousP))
                {
                    //Call the wiki update to force the system to look for new data
                    var wUtil = new WikiUtil();
                    wUtil.UpdateWiki(famousP.WikiLink);

                    UpdateFromWikiData(ref famousP);

                    _context.SaveChanges();
                    return RedirectToAction("Details", new { id });
                }

            }
            return View(famousP);

        }

        private Boolean UpdateFromWikiData(ref FamousPerson famousP)
        {
            var updateSuccess = true;

            if (!string.IsNullOrEmpty(famousP.WikiData().ImageUrl))
            {
                if (famousP.DateOfBirth.ToShortDateString() != DateTime.Parse(famousP.WikiData().DOB).ToShortDateString())
                {
                    DateTime fpDob;
                    if (DateTime.TryParse(famousP.WikiData().DOB.ToString(CultureInfo.InvariantCulture), out fpDob))
                    {
                        famousP.DateOfBirth = fpDob;
                    }
                    else
                    {
                        updateSuccess = false;
                    }
                }

                DateTime fpDod;
                if (famousP.DateOfDeath == null && DateTime.TryParse(famousP.WikiData().DOD.ToString(CultureInfo.InvariantCulture), out fpDod))
                {
                    famousP.DateOfDeath = fpDod;
                }

                if (famousP.DateOfDeath != null && (famousP.DateOfDeath.Value.ToShortDateString() != DateTime.Parse(famousP.WikiData().DOD.ToString(CultureInfo.InvariantCulture)).ToShortDateString()))
                {
                    if (DateTime.TryParse(famousP.WikiData().DOD.ToString(CultureInfo.InvariantCulture), out fpDod))
                    {
                        famousP.DateOfDeath = fpDod;
                    }
                    else
                    {
                        updateSuccess = false;
                    }
                }

                if (famousP.DisplayName != famousP.WikiData().DisplayName)
                {
                    famousP.DisplayName = famousP.WikiData().DisplayName;
                    if (string.IsNullOrEmpty(famousP.DisplayName))
                    {
                        updateSuccess = false;
                    }
                }
            }

            return updateSuccess;
        }

        [HttpPost]
        public JsonResult FppAutoComplete(string searchText, int maxResults)
        {
            var quickContext = new fppEntities(DataAccess.ffpCString);
            var acFpp = new List<acFamousPeople>();

            using (quickContext)
            {
                var result = from n in _context.FamousPersons
                             where n.DisplayName.Contains(searchText)
                             && n.DateOfDeath == null
                             orderby n.DisplayName
                             select n;

                List<FamousPerson> lFpp = result.Take(maxResults).ToList();

                acFpp.AddRange(lFpp.Select(itemFpp => new acFamousPeople
                                                          {
                                                              DisplayName = itemFpp.DisplayName,
                                                              Id = itemFpp.Id,
                                                              ImageUrl = itemFpp.WikiData().ImageUrl,
                                                              DoB = itemFpp.DateOfBirth.ToShortDateString(),
                                                              Age = DateUtil.GetAge(itemFpp.DateOfBirth).ToString(CultureInfo.InvariantCulture)
                                                          }));
            }

            return Json(acFpp);
        }

    }
}
